package com.aula.web.alex;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 *
 * @author lb
 */
public class Entrada
{
    private static InputStreamReader is = new InputStreamReader( System.in );
    // O campo br é uma instância da classe BufferedReader que usa is como argumento
    // para seu construtor.
    private static BufferedReader br = new BufferedReader( is );
    // O campo st é uma instância da classe StringTokenizer que será usada em vários
    // métodos na classe.
    private static StringTokenizer st;
    // O campo nt é uma instância da classe String que será usada em vários métodos
    // na classe.
    private static String nt;
    // O campo debug estabelece se mensagens de erro de conversão e leitura devem
    // ser mostradas ou não. O campo não pode ser modificado diretamente, mas
    // através de métodos específicos descritos abaixo.
    private static boolean debug = false;
    
    private static StringTokenizer getToken() throws IOException, NullPointerException
    {
        String s = br.readLine();
        return new StringTokenizer( s );
    }
    
    public static int readInt()
    {
        try
        {
            st = getToken(); // pega os tokens a partir da linha lida
            nt = st.nextToken(); // e a primeira String do token.
            // retorna o valor processado pela classe Integer
            return Integer.parseInt( nt );
        }
        catch ( IOException ioe ) // se houver algum erro de leitura
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Erro de entrada e saída lendo um int. Retorna " + 0 );
            }
            return 0; // retorna o valor default
        }
        catch ( NumberFormatException nfe ) // se houver algum erro de conversão
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Erro de conversão de " + nt + " para um int. Retorna " + 0 );
            }
            return 0;
        }
        
        catch ( NoSuchElementException nsee ) // se não houverem tokens
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Entrada não contém um int. Retorna " + 0 );
            }
            return 0; // retorna o valor default
        }
    }
    
    public static String readString()
    {
        try
        {
            nt = br.readLine(); // uma String lida diretamente
            
            if ( nt.trim().length() == 0 ) // nada foi entrado, então
            {
                return ""; // retorna o valor default
            }
            
            else
            {
                return nt; // retorna o que foi lido
            }
        }
        
        catch ( IOException ioe ) // se houver algum erro de leitura
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Erro de entrada e saída lendo um String. Retorna " + "" );
            }
            
            return ""; // retorna o valor default
        }
    } // fim do método readString

    /**
     * O método debugOn modifica o campo que indica que mensagens de erro deverão ser
     * mostradas, fazendo com que sejam mostradas até que o método debugOff seja chamado.
     */
    public static void debugOn()
    {
        debug = true;
        System.err.println( "KEYBOARD:: Mostrando mensagens de erro e avisos..." );
    }
    
    public static double readDouble()
    {
        double defaultvalue = 0.0;
        
        try
        {
            st = getToken(); // pega os tokens a partir da linha lida
            nt = st.nextToken(); // e a primeira String do token.
            // Verifica se o valor é aparentemente NaN ou infinito
            if ( nt.toLowerCase().startsWith( "nan" ) )
            {
                return Double.NaN;
            }
            else if ( nt.toLowerCase().startsWith( "inf" ) )
            {
                return Double.POSITIVE_INFINITY;
            }
            else if ( nt.toLowerCase().startsWith( "+inf" ) )
            {
                return Double.POSITIVE_INFINITY;
            }
            else if ( nt.toLowerCase().startsWith( "-inf" ) )
            {
                return Double.NEGATIVE_INFINITY;
            }
            // Retorna o valor processado pela classe Double
            return Double.parseDouble( nt );
        }
        catch ( IOException ioe ) // se houver algum erro de leitura
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Erro de entrada e saída lendo um double. "
                                    + "Retorna " + defaultvalue );
            }
            return defaultvalue; // retorna o valor default
        }
        catch ( NumberFormatException nfe ) // se houver algum erro de conversão
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Erro de conversão de " + nt + " para um double. "
                                    + "Retorna " + defaultvalue );
            }
            return defaultvalue;
        }
        catch ( NoSuchElementException nsee ) // se não houverem tokens
        {
            if ( debug ) // se for pedida a impressão de mensagens de erro
            {
                System.err.println( "KEYBOARD:: Entrada não contém um double. "
                                    + "Retorna " + defaultvalue );
            }
            return defaultvalue; // retorna o valor default
        }
    }
}
